<!-- 商品管理-品牌管理 -->
<template>
    <div>
        <!-- 卡片组件，显示品牌界面 -->
        <el-card class="box-card">
            <!-- 卡片顶部：添加品牌按钮 -->
            <el-button type="primary" icon="Plus" @click="addTrademark" v-hasButton="'add'">添加品牌</el-button>
            <!-- 表格组件：展示品牌列表
            table
                border：设置表格是否有边框
            table-column
                label：设置某一列的标题
                width：设置列宽
                align：设置该列对齐方式
                type：对应列的类型（selection多选框、index显示索引、expand可展开的按钮）
        -->
            <el-table :data="arr" border style="margin: 20px 0;">
                <el-table-column prop="id" label="序号" width="80px" align="center" type="index"></el-table-column>
                <el-table-column prop="tmName" label="品牌名称" width="width"></el-table-column>
                <!-- table-column 展示数据默认用div，也可更换为插槽 -->
                <el-table-column label="品牌LOGO" width="width">
                    <!-- row每一行的数据 -->
                    <template #="{ row, $index }">
                        <!-- <p>row.logoUrl</p> -->
                        <img :src="row.logoUrl" alt="图片加载失败" style="width: 100px;height: 100px;">
                    </template>
                </el-table-column>
                <el-table-column prop="prop" label="品牌操作" width="width">
                    <template #="{ row, $index }">
                        <el-button type="warning" size="small" icon="Edit" @click="updateTrademark(row)" v-hasButton="'update'"></el-button>
                        <el-popconfirm :title="`确认删除品牌${row.tmName}?`" width="auto" @confirm="removeTrademark(row.id)" v-hasButton="'remove'">
                            <template #reference>
                                <el-button type="danger" size="small" icon="Delete"></el-button>
                            </template>
                        </el-popconfirm>
                    </template>
                </el-table-column>
            </el-table>
            <!-- 分页器组件
            pagination
                v-model:current-page - 当前页码
                v-model:page-size - 每页展示条数
                page-sizes - 下拉菜单，选择每页展示个数的列表
                background - 设置分页器按钮的背景颜色
                layout - 设置分页器6个子组件的顺序 和 位置
                    '->' 表示将后续的子组件移至最右侧
        -->
            <el-pagination @size-change="sizeChange" @current-change="getTrademark" v-model:current-page="pageNo"
                v-model:page-size="limit" :page-sizes="[3, 5, 7, 9]" :background="true"
                layout=" prev, pager, next, jumper, ->,  sizes, total" :total="total" />
        </el-card>
        <!-- 对话框组件：添加/修改品牌 -->
        <!-- v-model：控制对话框的显示隐藏
        title：对话框左上角标题
     -->
        <el-dialog v-model="dialogFormVisible" :title="trademarkParams.id ? '修改品牌' : '添加品牌'">
            <el-form style="width: 80%" label-width="auto" :model="trademarkParams" ref="trademarkBox" :rules="addRules">
                <el-form-item label="品牌名称" prop="tmName">
                    <el-input placeholder="请输入品牌名称" v-model="trademarkParams.tmName"></el-input>
                </el-form-item>
                <el-form-item label="品牌LOGO" prop="logoUrl">
                    <!-- upload：action上传图片的请求路径，控制台查看post请求，注意添加 /api
                 -->
                    <el-upload class="avatar-uploader" action="/api/admin/product/fileUpload" :show-file-list="false"
                        :on-success="handleAvatarSuccess" :before-upload="beforeAvatarUpload">
                        <img v-if="trademarkParams.logoUrl" :src="trademarkParams.logoUrl" class="avatar" />
                        <el-icon v-else class="avatar-uploader-icon">
                            <Plus />
                        </el-icon>
                    </el-upload>
                </el-form-item>
            </el-form>
            <!-- 具名插槽 footer -->
            <template #footer>
                <el-button @click="cancel">取消</el-button>
                <el-button type="primary" @click="confirm" :loading="confirmloading"
                    :disabled="confirmloading">确定</el-button>
            </template>
        </el-dialog>
    </div>
</template>

<script setup lang="ts">
// 获取请求方法
import { reqTrademark, reqAddOrUpdateTrademark, reqDeleteTrademark } from '@/api/product/trademark'
import { nextTick, onMounted, reactive, ref } from 'vue';
import { Trademark, type Records, type TrademarkResponse } from '@/api/product/trademark/type'
// 图片墙
import type { UploadProps } from 'element-plus'
import { ElMessage } from 'element-plus'

// 分页器数据
// 当前页码
let pageNo = ref<number>(1);
// 每页展示数据的条数
let limit = ref<number>(3);
// 品牌总数
let total = ref<number>(0);
// 品牌信息数组
let arr = ref<Records>([]);
// 对话框的显示
let dialogFormVisible = ref<boolean>(false)
// 对话框“确定”按钮的加载（防止重复点击）
let confirmloading = ref(false);
// el-form组件实例
let trademarkBox = ref()

// 表单的品牌数据
let trademarkParams = reactive<Trademark>({
    tmName: '',
    logoUrl: ''
});

// 封装获取品牌的接口
// current-change方法默认传参pageNo，相当于pager=pageNo
// sizeChange无传参，则pager默认为1（调用时自动跳转到第一页）
const getTrademark = async (pager = 1) => {
    pageNo.value = pager
    let result: TrademarkResponse = await reqTrademark(pageNo.value, limit.value);
    if (result.code == 200) {
        // 品牌总数
        total.value = result.data.total;
        arr.value = result.data.records;
    }
}

// 组件挂载完毕钩子——获取第一页的三个品牌数据
onMounted(() => {
    getTrademark()
})

// 每页数据条数变化时调用的方法
const sizeChange = () => {
    getTrademark();
}

// “添加品牌”按钮
const addTrademark = () => {
    // 清除表单数据
    delete trademarkParams.id;
    // trademarkParams.tmName = '';
    // trademarkParams.logoUrl = '';
    // 对话框显示
    dialogFormVisible.value = true

    // 清空表单校验提示
    // 第一种：ts的问号语法（第一次点击，form组件还未加载完毕,form为undefined）
    // trademarkBox.value?.clearValidate();

    // 第二种：nextTick
    nextTick(() => {
        // 同时清空数据
        trademarkBox.value.resetFields();
    })
}

// “修改品牌”按钮
const updateTrademark = (row: Trademark) => {
    // 对话框显示
    dialogFormVisible.value = true
    // 获取待修改的品牌数据（ES6语法合并对象）
    Object.assign(trademarkParams, { id: row.id, tmName: row.tmName, logoUrl: row.logoUrl });
    // 清空表单校验提示
    nextTick(() => {
        trademarkBox.value.clearValidate();
    })
}

// 取消对话框
const cancel = () => {
    // 关闭对话框
    dialogFormVisible.value = false
    // 清空表单校验
    trademarkBox.value.clearValidate();
}

// 确定对话框（添加/修改品牌）
const confirm = async () => {
    // 发请求前，保证表单校验通过
    await trademarkBox.value.validate();
    // 按钮加载效果和禁用
    confirmloading.value = true;
    let result = await reqAddOrUpdateTrademark(trademarkParams);
    // 添加品牌成功
    if (result.code == 200) {
        // 弹出提示信息
        ElMessage({
            type: 'success',
            message: trademarkParams.id ? '修改品牌成功' : '添加品牌成功'
        })
        // 再次发请求获取全部品牌数据
        // 修改品牌->留在当前页，添加品牌->回到第一页
        getTrademark(trademarkParams.id ? pageNo.value : 1)
    }
    // 添加品牌失败
    else {
        // 弹出提示信息
        ElMessage({
            type: 'error',
            message: trademarkParams.id ? '修改品牌失败' : '添加品牌失败'
        })
    }
    // 关闭对话框
    dialogFormVisible.value = false
    // 按钮恢复
    confirmloading.value = false
}

// upload组件 —— 上传图片前触发的钩子函数（约束文件类型与大小）
const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
    // 限制文件类型和大小：png jpg gif 2M
    let imgType = ['image/jpeg', 'image/png', 'image/gif'];
    // 文件类型不匹配
    if (!imgType.includes(rawFile.type)) {
        ElMessage.error('上传文件格式为 PNG/JPG/GIF')
        return false
    }
    // 文件大小超过2M
    else if (rawFile.size / 1024 / 1024 > 2) {
        ElMessage.error('图片大小不能超过 2MB')
        return false
    }
    return true
}

// upload组件 —— 图片上传成功的钩子函数
const handleAvatarSuccess: UploadProps['onSuccess'] = (response, uploadFile) => {
    // response：本次上传图片服务器返回的响应数据  response.data为图片上传后的路径
    trademarkParams.logoUrl = response.data;
    // 重新校验表单项
    trademarkBox.value.clearValidate('logoUrl');
}

// 品牌名称自定义规则
const validatorTmName = (rule: any, value: any, callback: any) => {
    // ^\s非空字符
    if (/^[^\s]{2,}$/.test(value)) callback()
    else callback(new Error('请输入至少两位的非空品牌名称'))
}

// 表单校验规则
const addRules = {
    tmName: [
        { required: true, validator: validatorTmName, trigger: 'blur' }
    ],
    // trigger对upload失效
    logoUrl: [
        { required: true, message: '请选择品牌LOGO', trigger: 'blur' }
    ]
}

// 删除品牌：气泡确认框的回调
const removeTrademark = async (id: number) => {
    // 发送删除请求
    let result = await reqDeleteTrademark(id);
    if (result.code == 200) {
        // 显示提示信息
        ElMessage({
            type: 'success',
            message: '删除品牌成功'
        })
        // 再次获取已有品牌数据（留在当前页或上一页）
        getTrademark(arr.value.length - 1>0 ? pageNo.value : pageNo.value - 1);
    }
    else {
        ElMessage({
            type: 'error',
            message: '删除品牌失败'
        })
    }
}
</script>

<!-- el-upload样式，参考官网 -->
<style scoped>
.avatar-uploader .avatar {
    width: 178px;
    height: 178px;
    display: block;
}
</style>

<style>
.avatar-uploader .el-upload {
    border: 1px dashed var(--el-border-color);
    border-radius: 6px;
    cursor: pointer;
    position: relative;
    overflow: hidden;
    transition: var(--el-transition-duration-fast);
}

.avatar-uploader .el-upload:hover {
    border-color: var(--el-color-primary);
}

.el-icon.avatar-uploader-icon {
    font-size: 28px;
    color: #8c939d;
    width: 178px;
    height: 178px;
    text-align: center;
}
</style>